#include "systemLog.h"
#include "../../config/config.h"

#include <time.h>
#include <stdarg.h>
#include <string.h>

// 初始化系统日志互斥锁
pthread_mutex_t g_system_log_lock = PTHREAD_MUTEX_INITIALIZER;

// 全局系统日志文件指针
FILE *g_system_log_file = NULL;

// 默认日志等级
int g_log_level = SYSTEM_LOG_LEVEL_DEBUG;

// 判断是否显示上下文信息
int should_show_context(system_log_level_t msg_level)
{
    // 只有在调试级别才显示上下文信息
    if (msg_level == SYSTEM_LOG_LEVEL_DEBUG)
    {
        return 1;
    }

    return 0;
}

// 获取日志级别字符串表示
char *get_log_level_string(system_log_level_t level)
{
    switch (level)
    {
    case SYSTEM_LOG_LEVEL_DEBUG:
        return "DEBUG";
    case SYSTEM_LOG_LEVEL_INFO:
        return "INFO";
    case SYSTEM_LOG_LEVEL_WARN:
        return "WARN";
    case SYSTEM_LOG_LEVEL_ERROR:
        return "ERROR";
    case SYSTEM_LOG_LEVEL_FATAL:
        return "FATAL";
    default:
        return "UNKNOWN";
    }
}

// 获取错误码字符串表示
char *get_error_code_string(system_error_code_t code)
{
    switch (code)
    {
    case SYSTEM_ERR_OK:
        return "No error";
    case SYSTEM_ERR_FILE_NOT_FOUND:
        return "File not found";
    case SYSTEM_ERR_PERMISSION_DENIED:
        return "Permission denied";
    case SYSTEM_ERR_OUT_OF_MEMORY:
        return "Out of memory";
    case SYSTEM_ERR_INVALID_ARGUMENT:
        return "Invalid argument";
    case SYSTEM_ERR_NETWORK_FAILURE:
        return "Network failure";
    case SYSTEM_ERR_NULL_POINTER:
        return "Null pointer exception";

    /* DB 错误 */
    case SYSTEM_ERR_DB_BASE:
        return "DB error";
    case SYSTEM_ERR_DB_INIT:
        return "DB init failed";
    case SYSTEM_ERR_DB_CONNECT:
        return "DB connect failed";
    case SYSTEM_ERR_DB_AUTH:
        return "DB auth failed";

    /* 队列错误 */
    case SYSTEM_ERR_QUEUE_BASE:
        return "Queue error";
    case SYSTEM_ERR_QUEUE_EMPTY:
        return "Queue empty";
    case SYSTEM_ERR_QUEUE_INVALID:
        return "Queue invalid";

    /* worker/线程错误 */
    case SYSTEM_ERR_WORKER_BASE:
        return "Worker error";
    case SYSTEM_ERR_WORKER_THREAD_CREATE:
        return "Worker thread create failed";
    case SYSTEM_ERR_WORKER_THREAD_JOIN:
        return "Worker thread join failed";

    /* epoll 错误 */
    case SYSTEM_ERR_EPOLL_BASE:
        return "Epoll error";
    case SYSTEM_ERR_EPOLL_CREATE:
        return "Epoll create failed";
    case SYSTEM_ERR_EPOLL_ADD:
        return "Epoll add fd failed";
    case SYSTEM_ERR_EPOLL_DELETE:
        return "Epoll delete fd failed";

    /* 配置错误 */
    case SYSTEM_ERR_CONFIG_BASE:
        return "Config error";
    case SYSTEM_ERR_CONFIG_FILE:
        return "Config file open failed";
    case SYSTEM_ERR_CONFIG_PARSE:
        return "Config parse failed";
    case SYSTEM_ERR_CONFIG_MISSING:
        return "Config missing required field";
    case SYSTEM_ERR_CONFIG_OVERFLOW:
        return "Config field overflow";

    /* 会话管理错误 */
    case SYSTEM_ERR_SESSION_BASE:
        return "Session error";
    case SYSTEM_ERR_SESSION_NOT_FOUND:
        return "Session not found";
    case SYSTEM_ERR_SESSION_ALREADY_EXISTS:
        return "Session already exists";

    /* 哈希表错误 */
    case SYSTEM_ERR_HASHMAP_BASE:
        return "HashMap error";
    case SYSTEM_ERR_HASHMAP_NOT_FOUND:
        return "HashMap key not found";
    case SYSTEM_ERR_HASHMAP_ALREADY_EXISTS:
        return "HashMap key already exists";

    /* 令牌错误 */
    case SYSTEM_ERR_TOKEN_BASE:
        return "Token error";
    case SYSTEM_ERR_TOKEN_INVALID:
        return "Token is invalid";
    case SYSTEM_ERR_TOKEN_ENCODE_FAILED:
        return "Token encode failed";
    case SYSTEM_ERR_TOKEN_DECODE_FAILED:
        return "Token decode failed";

    case SYSTEM_ERR_LOG_NOT_INITIALIZED:
        return "Log system not initialized";
    case SYSTEM_ERR_LOG_IO:
        return "Log I/O error";
    case SYSTEM_ERR_LOG_PATH_INVALID:
        return "Log path invalid or not writable";
    default:
        return "Unknown error";
    }
}

system_error_code_t system_log_init(const char *log_file_path, const system_log_level_t initial_level)
{
    // TODO: 支持NULL路径，使用默认日志文件路径，目前仅做参数检查
    if (log_file_path == NULL)
    {
        log_file_path = g_system_log_path;
    }

    // 设置初始日志等级
    if (initial_level == SYSTEM_LOG_LEVEL_UNKNOWN ||
        initial_level < SYSTEM_LOG_LEVEL_DEBUG || initial_level > SYSTEM_LOG_LEVEL_FATAL)
    {
        return SYSTEM_ERR_INVALID_ARGUMENT;
    }
    g_log_level = initial_level;

    // 打开日志文件
    FILE *file = fopen(log_file_path, "a");
    // 打开失败，使用fprintf输出错误码，并返回对应错误码
    if (file == NULL)
    {
        fprintf(stderr, "Failed to open log file: %s\n", log_file_path);
        return SYSTEM_ERR_LOG_PATH_INVALID;
    }

    // 成功，设置全局日志文件指针
    // 暂时不考虑多线程初始化问题
    g_system_log_file = file;

    return SYSTEM_ERR_OK;
}

system_error_code_t system_log_write(system_log_level_t level, system_error_code_t err_code,
                                     const char *file, const char *func, int line,
                                     const char *format, ...)
{

    // 检查日志系统是否初始化
    if (g_system_log_file == NULL)
    {
        return SYSTEM_ERR_LOG_NOT_INITIALIZED;
    }

    // 向日志文件写入日志条目
    // 上锁
    pthread_mutex_lock(&g_system_log_lock);
    // 获取当前时间
    time_t now = time(NULL);
    struct tm *tm_info = localtime(&now);
    char time_buffer[26];
    strftime(time_buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
    // 判断是否需要输出上下文信息
    if (file == NULL || func == NULL || line == 0)
    {
        // 写入 时间 日志级别 错误码
        fprintf(g_system_log_file, "[%s] [%s] [Error: %s] ",
                time_buffer,
                get_log_level_string(level),
                get_error_code_string(err_code));
    }
    else
    {
        // 写入 时间 日志级别 错误码 源文件 函数名 行号
        fprintf(g_system_log_file, "[%s] [%s] [Error: %s] [%s:%s:%d] ",
                time_buffer,
                get_log_level_string(level),
                get_error_code_string(err_code),
                file,
                func,
                line);
    }
    // 处理可变参数
    va_list args;
    va_start(args, format);
    vfprintf(g_system_log_file, format, args);
    va_end(args);
    // 换行
    fprintf(g_system_log_file, "\n");
    // 刷新文件缓冲区
    fflush(g_system_log_file);
    // 解锁
    pthread_mutex_unlock(&g_system_log_lock);

    return SYSTEM_ERR_OK;
}